/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package entityappclient;

import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
import javax.ejb.EJB;
import persistence.entity.Account;
import persistence.entity.Accounttransaction;
import persistence.entity.Biller;
import persistence.entity.Customer;
import session.stateless.*;

/**
 *
 * @author Mark
 */
public class TMClient {

    @EJB
    private static AccounttransactionFacadeRemote accounttransactionFacade;
    @EJB
    private static AccountTransactionHelperRemote accountTransactionHelper;
    @EJB
    private static AccountHelperRemote accountHelper;
    @EJB
    private static BillerFacadeRemote billerFacade;
    @EJB
    private static CustomerHelperBeanRemote customerHelperBean;
    @EJB
    private static AccountFacadeRemote accountFacade;
    @EJB
    private static CustomerFacadeRemote customerFacade;
    private Scanner scan = new Scanner(System.in);

    public static void main(String[] args) {
        //new TMClient().oldRun();
        new TMClient().run();
    }

    public void run() {
        String input;
        //Main loop
        while (true) {
            //Display logo
            System.out.println("     \\`\\/\\/\\/`/     /===========================\\");
            System.out.println("      )======(      |                           |");
            System.out.println("    .'        '.    |          Welcome          |");
            System.out.println("   /    _||__   \\   |        to Swinbank        |");
            System.out.println("  /    (_||_     \\  |                           |");
            System.out.println(" |     __||_)     | |      We !care about       |");
            System.out.println(" |       ||       | |        your safety        |");
            System.out.println(" '.              .' |                           |");
            System.out.println("   '------------'   \\===========================/");
            //Perform login
            int custID = getInt("Please enter your teller ID");

            String password = getString("Please enter your password");

            //BUG: Possible bug on authentication, get Null pointer exception
            boolean authenticated = customerFacade.authenticate(custID, password, false);
            if (!authenticated) {
                System.out.println("Login Failed");
                //Authentication failed, restart loop
                continue;
            }

            boolean exit = false;
            while (!exit) {
                //Print main menu
                System.out.println("");
                System.out.println("Main Menu");
                System.out.println("1. Customers");
                System.out.println("2. Accounts");
                System.out.println("3. Transactions");
                System.out.println("4. Exit");
                //Get option
                int option = getInt("Please select an option");
                switch (option) {
                    case 1:
                        customers();
                        break;
                    case 2:
                        accounts();
                        break;
                    case 3:
                        transactions();
                        break;
                    case 4:
                        exit = true;
                        break;
                    default:
                        System.out.println("Invalid Selection");
                        break;
                }
            }
        }
    }

    //Customer related menu options
    private void customers() {
        boolean back = false;
        while (!back) {
            //Print main menu
            System.out.println("");
            System.out.println("Customer Menu");
            System.out.println("1. Create Customer");
            System.out.println("2. View Customer");
            System.out.println("3. View all Customers");
            System.out.println("4. Update Customer");
            System.out.println("5. Disable Customer");
            System.out.println("6. Back");
            //Get option
            int option = getInt("Please select an option");
            switch (option) {
                case 1:
                    createCustomer();
                    break;
                case 2:
                    viewCustomer();
                    break;
                case 3:
                    viewCustomers();
                    break;
                case 4:
                    updateCustomer();
                    break;
                case 5:
                    disableCustomer();
                    break;
                case 6:
                    back = true;
                    System.out.println("");
                    break;
                default:
                    System.out.println("Invalid Selection");
                    break;
            }
        }
    }

    //Add a new customer
    private void createCustomer() {
        String name = getString("Name");
        String password = getString("Password");
        String address = getString("Address");
        String phone = getString("Phone");
        Customer newCust = customerFacade.createCustomer(name, address, phone, password);
        System.out.println("Customer created");
        System.out.println("New Customer ID: " + newCust.getCustId());
    }

    //View a customer
    private void viewCustomer() {
        int custID = getInt("Customer ID");
        Customer cust = customerFacade.find(custID);
        if (cust != null) {
            ConsoleTable ct = ConsoleTable.getCustomerTable();
            String[] details = new String[7];
            details[0] = cust.getCustId().toString();
            details[1] = cust.getCustName();
            details[2] = cust.getCustAddress();
            details[3] = cust.getCustPhone();
            details[4] = cust.getCustPassword();
            details[5] = cust.getCustIsTeller();
            details[6] = cust.getIsdisabled();
            ct.addRow(details);
            ct.printTable();
        } else {
            System.out.println("Customer not found");
        }
    }

    //View all custmers
    private void viewCustomers() {
        //Get all the customers
        List<Customer> customers = customerFacade.findAll();
        //Get ConsoleTable
        ConsoleTable ct = ConsoleTable.getCustomerTable();
        //Add all entries
        for (int x = 0; x < customers.size(); x++) {
            Customer cust = customers.get(x);
            String[] details = new String[7];
            details[0] = cust.getCustId().toString();
            details[1] = cust.getCustName();
            details[2] = cust.getCustAddress();
            details[3] = cust.getCustPhone();
            details[4] = cust.getCustPassword();
            details[5] = cust.getCustIsTeller();
            details[6] = cust.getIsdisabled();
            ct.addRow(details);
        }
        //Print page by page
        for (int x = 0; x < ct.getNoOfPages(); x++) {
            ct.printPagedTable(x);
            System.out.println("Press enter for next page");
            scan.nextLine();
        }
    }

    //BUG: Cannot change custID, bug in CustomerFacade
    private void updateCustomer() {
        //Find the customer to update
        int custID = getInt("Enter Customer ID");
        Customer cust = customerFacade.find(custID);
        if (cust != null) {
            ConsoleTable ct = ConsoleTable.getCustomerTable();
            String[] details = new String[7];
            details[0] = cust.getCustId().toString();
            details[1] = cust.getCustName();
            details[2] = cust.getCustAddress();
            details[3] = cust.getCustPhone();
            details[4] = cust.getCustPassword();
            details[5] = cust.getCustIsTeller();
            details[6] = cust.getIsdisabled();
            ct.addRow(details);
            ct.printTable();
            //Asks what to update
            System.out.println("");
            System.out.println("What would you like to update");
            System.out.println("1. Name");
            System.out.println("2. Address");
            System.out.println("3. Phone");
            System.out.println("4. Password");
            int option = getInt("Please select an option");
            String input;
            switch (option) {
                case 1:
                    input = getString("Name");
                    customerFacade.updateName(custID, input);
                    break;
                case 2:
                    input = getString("Address");
                    customerFacade.updateAddress(custID, input);
                    break;
                case 3:
                    input = getString("Phone");
                    customerFacade.updatePhone(custID, input);
                    break;
                case 4:
                    input = getString("Password");
                    customerFacade.updatePassword(custID, input);
                    break;
                default:
                    System.out.println("Invalid Option");
            }
        } else {
            System.out.println("Customer not found");
        }
    }

    private void disableCustomer() {
        //Find the customer to disable
        int custID = getInt("Enter Customer ID");
        Customer cust = customerFacade.find(custID);
        if (cust != null) {
            customerHelperBean.removeCustomer(custID);
            System.out.println("Customer disabled");
        } else {
            System.out.println("Customer not found");
        }

    }

    //Account related menu options
    private void accounts() {
        boolean back = false;
        while (!back) {
            //Print main menu
            System.out.println("");
            System.out.println("Account Menu");
            System.out.println("1. Create Account");
            System.out.println("2. View Account");
            System.out.println("3. View Customers Accounts");
            System.out.println("4. Disable Account");
            System.out.println("5. Back");
            //Get option
            int option = getInt("Please select an option");
            switch (option) {
                case 1:
                    createAccount();
                    break;
                case 2:
                    viewAccount();
                    break;
                case 3:
                    viewCustomerAccounts();
                    break;
                case 4:
                    disableAccount();
                    break;
                case 5:
                    back = true;
                    break;
                default:
                    System.out.println("Invalid Selection");
                    break;
            }
        }
    }

    private void createAccount() {
        //Determine account type
        char type = getCustOrBiller();
        Integer id;
        if (type == 'C') {
            id = getInt("Enter Customer ID");
            Customer cust = customerFacade.find(id);
            if (cust == null) {
                System.out.println("Invalid customer ID");
                return;
            }
            accountHelper.createCustomerAccount(id);
        } else {
            id = getInt("Enter Biller ID");
            Biller biller = billerFacade.find(id);
            if (biller == null) {
                System.out.println("Invalid biller Id");
                return;
            }
            accountHelper.createBillerAccount(id);
        }
        System.out.println("Account Created for customer: " + id);
    }

    private void viewAccount() {
        //Get the ID
        int accId = getInt("Enter Account ID");
        Account acc = accountFacade.find(accId);
        if (acc != null) {
            ConsoleTable ct = ConsoleTable.getAccountTable();
            String[] details = new String[5];
            details[0] = acc.getAccountId().toString();
            details[1] = String.valueOf(acc.getAccountType());
            details[2] = Integer.toString(acc.getAccountBalance());
            if (acc.getAccountType() == 'C') {
                details[3] = Integer.toString(acc.getAccountCustomerId().getCustId());
            } else {
                details[3] = Integer.toString(acc.getAccountBillerId().getBillerId());
            }
            details[4] = acc.getIsdisabled();
            ct.addRow(details);
            ct.printTable();
        } else {
            System.out.println("Account not found");
        }
    }

    private void viewCustomerAccounts() {
        //Determine account type
        char type = getCustOrBiller();
        Integer id;
        Collection<Account> accounts;
        //Get the user ID and accounts
        if (type == 'C') {
            id = getInt("Enter Customer ID");
            accounts = accountFacade.getAccountList(id, true);
            if (accounts == null) {
                System.out.println("No accounts found for ID: " + id);
                return;
            }
        } else {
            id = getInt("Enter Biller ID");
            accounts = accountFacade.getAccountList(id, false);
            if (accounts == null) {
                System.out.println("No accounts found for ID: " + id);
                return;
            }
        }
        //Loop through accounts
        ConsoleTable ct = ConsoleTable.getAccountTable();
        for (Account acc : accounts) {
            String[] details = new String[5];
            details[0] = acc.getAccountId().toString();
            details[1] = String.valueOf(acc.getAccountType());
            details[2] = Integer.toString(acc.getAccountBalance());
            if (type == 'C') {
                details[3] = Integer.toString(acc.getAccountCustomerId().getCustId());
            } else {
                details[3] = Integer.toString(acc.getAccountBillerId().getBillerId());
            }
            details[4] = acc.getIsdisabled();
            ct.addRow(details);
        }
        //Print page by page
        for (int x = 0; x < ct.getNoOfPages(); x++) {
            ct.printPagedTable(x);
            System.out.println("Press enter for next page");
            scan.nextLine();
        }
    }

    private void disableAccount() {
        //Get account number
        int accId = getInt("Please enter account ID");
        Account acc = accountFacade.find(accId);
        if (acc != null) {
            accountHelper.disableAccount(accId);
        } else {
            System.out.println("No account found with ID: " + accId);
        }
    }

    //Transaction menu options
    private void transactions() {
        boolean back = false;
        while (!back) {
            //Print main menu
            System.out.println("");
            System.out.println("Transaction Menu");
            System.out.println("1. Deposit");
            System.out.println("2. Withdrawl");
            System.out.println("3. Transfer");
            System.out.println("4. View All Transactions");
            System.out.println("5. View Transaction for Account");
            System.out.println("6. Back");
            //Get option
            int option = getInt("Please select an option");
            switch (option) {
                case 1:
                    deposit();
                    break;
                case 2:
                    withdrawl();
                    break;
                case 3:
                    transfer();
                    break;
                case 4:
                    viewAllTransactions();
                    break;
                case 5:
                    viewAccountTransactions();
                    break;
                case 6:
                    back = true;
                    break;
                default:
                    System.out.println("Invalid Selection");
                    break;
            }
        }
    }

    private void deposit() {
        //Get account to deposit in to
        int accId = getInt("Account to deposit in to");
        Account acc = accountFacade.find(accId);
        if (acc != null) {
            //Get ammount to deposit
            int depositAmmount = getInt("Deposit how much (cents)");
            //Get description
            String description = getString("Trasaction description");
            Accounttransaction transaction = accountTransactionHelper.createDeposit(depositAmmount, description, accId);
            if (transaction != null) {
                System.out.println("Transaction completed sucessfully");
            } else {
                System.out.println("Error performing transaction");
            }
        } else {
            System.out.println("No account found with ID: " + accId);
        }
    }

    private void withdrawl() {
        //Get account to withdraw from
        int accId = getInt("Account to withdraw from");
        Account acc = accountFacade.find(accId);
        if (acc != null) {
            //Get ammount to withdraw
            int depositAmmount = getInt("Withdraw how much (cents)");
            //Get description
            String description = getString("Trasaction description");
            Accounttransaction transaction = accountTransactionHelper.createWithdrawl(depositAmmount, description, accId);
            if (transaction != null) {
                System.out.println("Transaction completed sucessfully");
            } else {
                System.out.println("Error performing transaction");
            }
        } else {
            System.out.println("No account found with ID: " + accId);
        }
    }

    private void transfer() {
        //Get from account
        int fromAccId = getInt("Account to transfer from");
        Account fromAcc = accountFacade.find(fromAccId);
        if (fromAcc != null) {
            int toAccId = getInt("Acccount to transfer to");
            Account toAcc = accountFacade.find(toAccId);
            if (toAcc != null) {
                //Get amount to transfer
                int amount = getInt("Transfer how much (cents)");
                String description = getString("Transaction Description");
                Accounttransaction transaction = accountTransactionHelper.createTransfer(amount, description, fromAccId, toAccId);
                if (transaction != null) {
                    System.out.println("Transaction completed sucessfully");
                } else {
                    System.out.println("Error performing transaction");
                }
            } else {
                System.out.println("No account found with ID: " + toAccId);
            }
        } else {
            System.out.println("No account found with ID: " + fromAccId);
        }
    }

    private void viewAllTransactions() {
        ConsoleTable ct = ConsoleTable.getTransactionTable();
        //Get all transactions
        Collection<Accounttransaction> transactions = accounttransactionFacade.findAll();
        for (Accounttransaction transaction : transactions) {
            String[] details = new String[7];
            details[0] = Integer.toString(transaction.getTransId());
            details[1] = Character.toString(transaction.getTransType());
            //Format the date
            SimpleDateFormat formatter = new SimpleDateFormat("d/M/y H:m:s");
            details[2] = formatter.format(transaction.getTransDate());
            details[3] = Integer.toString(transaction.getTransAmount());
            details[4] = transaction.getTransDescription();
            //Null check on to and from account
            if (transaction.getTransFromAccount() != null) {
                details[5] = Integer.toString(transaction.getTransFromAccount().getAccountId());
            } else {
                details[5] = "";
            }
            if (transaction.getTransToAccount() != null) {
                details[6] = Integer.toString(transaction.getTransToAccount().getAccountId());
            } else {
                details[6] = "";
            }
            ct.addRow(details);
        }
        //Print page by page
        for (int x = 0; x < ct.getNoOfPages(); x++) {
            ct.printPagedTable(x);
            System.out.println("Press enter for next page");
            scan.nextLine();
        }
    }

    private void viewAccountTransactions() {
        //Get account ID
        int accID = getInt("Account ID");
        Account account = accountFacade.find(accID);
        if (account != null) {
            List<Accounttransaction> transactions = accountTransactionHelper.getTransactionsForAccount(account);
            ConsoleTable ct = ConsoleTable.getTransactionTable();
            System.out.println("no of trans: " + transactions.size());
            for (Accounttransaction transaction : transactions) {
                String[] details = new String[7];
                details[0] = Integer.toString(transaction.getTransId());
                details[1] = Character.toString(transaction.getTransType());
                //Format the date
                SimpleDateFormat formatter = new SimpleDateFormat("d/M/y H:m:s");
                details[2] = formatter.format(transaction.getTransDate());
                details[3] = Integer.toString(transaction.getTransAmount());
                details[4] = transaction.getTransDescription();
                //Null check on to and from account
                if (transaction.getTransFromAccount() != null) {
                    details[5] = Integer.toString(transaction.getTransFromAccount().getAccountId());
                } else {
                    details[5] = "";
                }
                if (transaction.getTransToAccount() != null) {
                    details[6] = Integer.toString(transaction.getTransToAccount().getAccountId());
                } else {
                    details[6] = "";
                }
                ct.addRow(details);
            }
            //Print page by page
            for (int x = 0; x < ct.getNoOfPages(); x++) {
                ct.printPagedTable(x);
                System.out.println("Press enter for next page");
                scan.nextLine();
            }
        } else {
            System.out.println("Account not found");
        }
    }

    //Get an int, block until provided
    private int getInt(String request) {
        int input = 0;
        while (true) {
            try {
                System.out.print(request + ": ");
                input = Integer.parseInt(scan.nextLine());
                break;
            } catch (NumberFormatException ex) {
                System.out.println("Please enter a number");
            }
        }
        return input;
    }

    //Get a string
    private String getString(String request) {
        System.out.print(request + ": ");
        return scan.nextLine();
    }

    //Get a boolean
    private boolean getBoolean(String request) {
        boolean bool;
        while (true) {
            System.out.println(request + ": ");
            String input = scan.nextLine();
            if (input.equalsIgnoreCase(Boolean.TRUE.toString())) {
                bool = true;
                break;
            } else if (input.equalsIgnoreCase(Boolean.FALSE.toString())) {
                bool = false;
                break;
            }
            System.out.println("Please enter 'true' or 'false'");
        }
        return bool;

    }

    //Get a Customer or Biller char
    private char getCustOrBiller() {
        char type;
        while (true) {
            System.out.print("Please enter 'C' or 'B' for Customer of Biller: ");
            String input = scan.nextLine();
            if (input.isEmpty() || input.charAt(0) == 'c' || input.charAt(0) == 'C') {
                type = 'C';
                break;
            } else if (input.isEmpty() || input.charAt(0) == 'b' || input.charAt(0) == 'B') {
                type = 'B';
                break;
            }
        }
        return type;
    }
}
